package com.mt.restaurant.service.sale.impl;

import com.alibaba.fastjson.JSON;
import com.mt.restaurant.dao.sale.SaleOrderDao;
import com.mt.restaurant.dao.sale.SaleOrderSettlementDao;

import com.mt.common.core.exception.BusinessException;
import com.mt.common.core.web.base.PageDTO;
import com.mt.common.core.web.base.PageResultDTO;
import com.mt.common.core.web.base.BaseEntity;
import com.mt.common.core.web.BaseService;
import com.mt.restaurant.entity.material.Cost;
import com.mt.restaurant.entity.sale.MenuSaleRecord;
import com.mt.restaurant.service.material.CostService;
import com.mt.restaurant.service.sale.MenuSaleRecordService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mt.restaurant.entity.sale.SaleOrderSettlement;
import com.mt.restaurant.service.sale.SaleOrderSettlementService;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.xml.crypto.Data;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class SaleOrderSettlementServiceBean extends BaseService implements SaleOrderSettlementService {

    private static Logger logger = LogManager.getLogger();

	@Autowired
	private SaleOrderSettlementDao saleOrderSettlementDao;

	@Resource
	private RedisTemplate<String, List<SaleOrderSettlement>> redisTemplate;

	@Autowired
	StringRedisTemplate stringRedisTemplate;

	@Autowired
	private SaleOrderDao saleOrderDao;

	@Autowired
	private CostService costService;
	@Autowired
	private MenuSaleRecordService menuSaleRecordService;
	/**
	 * 根据分页参数查询销售订单结算集合
	 *
	 * @param pageDTO 分页条件
	 */
	@Override
	public PageResultDTO findSaleOrderSettlements(PageDTO pageDTO){
        pageDTO.setStartIndex((pageDTO.getCurrentPage()-1)*pageDTO.getPageSize());
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrderSettlements(pageDTO);
		List<SaleOrderSettlement> saleOrderSettlementDTOS = this.saleOrderSettlementDao.findSaleOrderSettlements(pageDTO);
		Long totalCount = this.saleOrderSettlementDao.findSaleOrderSettlementTotalCount(pageDTO);

		PageResultDTO pageResultDTO = new PageResultDTO();
		pageResultDTO.setTotalCount(totalCount);
		pageResultDTO.setDatas(saleOrderSettlementDTOS);

		return pageResultDTO;
	}

	/**
	 * 查询全部销售订单结算集合
	 *
	 */
	@Override
	public List<SaleOrderSettlement> findAllSaleOrderSettlements(){
		return this.saleOrderSettlementDao.findAllSaleOrderSettlements();
	}

	/**
	 * 查询所有销售订单结算集合(只提取ID 和 Name)
	 *
	 */
	@Override
	public List<SaleOrderSettlement> findAllSaleOrderSettlementsWithIdName(){
		//TODO:请在此校验参数的合法性
		this.validateFindAllSaleOrderSettlementsWithIdName();
		return this.saleOrderSettlementDao.findAllSaleOrderSettlementsWithIdName();
	}

	/**
	 * 根据名称查询销售订单结算集合(只提取ID 和 Name)
	 *
	 * @param saleOrderSettlementName 名称
	 */
	@Override
	public List<SaleOrderSettlement> findSaleOrderSettlementsWithIdNameByName(String saleOrderSettlementName){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrderSettlementsWithIdNameByName(saleOrderSettlementName);
		//TODO:缓存取对应参数
		Set<String> keys = stringRedisTemplate.keys("searchData:SaleOrderSettlement_where_saleOrderSettlementName_" + saleOrderSettlementName);
		List<SaleOrderSettlement> saleOrderSettlements = new ArrayList<>();
		if (keys.isEmpty()) {
		saleOrderSettlements = this.saleOrderSettlementDao.findSaleOrderSettlementsWithIdNameByName(saleOrderSettlementName);
		redisTemplate.opsForValue().set("searchData:SaleOrderSettlement_where_saleOrderSettlementName_" + saleOrderSettlementName, saleOrderSettlements, 30, TimeUnit.DAYS);
		} else {
		saleOrderSettlements = redisTemplate.opsForValue().get("searchData:SaleOrderSettlement_where_saleOrderSettlementName_" + saleOrderSettlementName);
		}
		return saleOrderSettlements;
	}

	/**
	 * 根据ID查询指定的销售订单结算(只提取ID 和 Name)
	 *
	 * @param saleOrderSettlementId Id
	 */
	@Override
	public SaleOrderSettlement findSaleOrderSettlementsWithIdNameById(Long saleOrderSettlementId){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrderSettlementsWithIdNameById(saleOrderSettlementId);
		return this.saleOrderSettlementDao.findSaleOrderSettlementsWithIdNameById(saleOrderSettlementId);
	}

	/**
	 * 根据ID查询指定的销售订单结算
	 *
	 * @param saleOrderSettlementId Id
	 */
	@Override
	public SaleOrderSettlement findSaleOrderSettlement(Long saleOrderSettlementId){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrderSettlement(saleOrderSettlementId);
		return this.saleOrderSettlementDao.findSaleOrderSettlement(saleOrderSettlementId);
	}

	/**
	 * 根据ID查询指定的销售订单结算(包含外键)
	 *
	 * @param saleOrderSettlementId Id
	 */
	@Override
	public SaleOrderSettlement findSaleOrderSettlementWithForeignName(Long saleOrderSettlementId){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrderSettlementWithForeignName(saleOrderSettlementId);
		return this.saleOrderSettlementDao.findSaleOrderSettlementWithForeignName(saleOrderSettlementId);
	}

	/**
	 * 新增销售订单结算
	 *
	 * @param saleOrderSettlement 实体对象
	 */
	@Override
	public SaleOrderSettlement saveSaleOrderSettlement(SaleOrderSettlement saleOrderSettlement){
		//TODO:请在此校验参数的合法性
		this.validateSaveSaleOrderSettlement(saleOrderSettlement);
		//TODO:填充公共参数
		this.setSavePulicColumns(saleOrderSettlement);
		Date date = new Date();
		saleOrderSettlement.setSettlDate(date);
		saleOrderSettlement.setSerialNum(String.valueOf(date.getTime()));
		Long rows = this.saleOrderSettlementDao.saveSaleOrderSettlement(saleOrderSettlement);

		saleOrderDao.updateSaleOrderStatus(saleOrderSettlement.getSaleOrderId(),"已结算");

		Cost cost=new Cost();
		cost.setStatus("收入");
		cost.setType("菜品销售");
		cost.setTotal(saleOrderSettlement.getSettlPrice());
		cost.setPrice(saleOrderSettlement.getSettlPrice());
		cost.setAmount(1.0);
		costService.saveCost(cost);
		if(rows != 1)
		{
			String error = "新增保存销售订单结算出错，数据库应该返回1,但返回了 "+rows;
			throw new BusinessException(error);
		}
		return saleOrderSettlement;
	}
	//@Autowired
	//private ApplicationContext applicationContext;
	//public void demo(){
	//	Map<String, Object> controllers = applicationContext.getBeansWithAnnotation(RestController.class);
	//
	//	for (Map.Entry<String, Object> entry : controllers.entrySet()) {
	//		Object value = entry.getValue();
	//		System.out.println("拿到controller："+entry.getKey()+"，拿到value："+value);
	//		Class<?> aClass = AopUtils.getTargetClass(value);
	//		System.out.println("拿到Class:"+aClass);
	//		//Method[] methods = value.getClass().getMethods();
	//		//List<String> list = new ArrayList<>();
	//		//for (Method method : methods) {
	//		//	PreAuthorize anno = method.getAnnotation(PreAuthorize.class);
	//		//	if (anno != null) {
	//		//		String annotationValue = anno.value();
	//		//		annotationValue = annotationValue.substring(14, annotationValue.length() - 2);
	//		//		list.add(annotationValue);
	//		//	}
	//		//}
	//		RequestMapping annotation = aClass.getAnnotation(RequestMapping.class);
	//		RequestMapping declaredAnnotation = aClass.getDeclaredAnnotation(RequestMapping.class);
	//
	//		List<Method> methods = Arrays.asList(aClass.getMethods());
	//		//System.out.println("Public Methods:" + methods);
	//		List<Method> declaredMethods = Arrays.asList(aClass.getDeclaredMethods());
	//		for (int i = 0; i < declaredMethods.size() ; i++) {
	//			GetMapping getMapping = declaredMethods.get(i).getAnnotation(GetMapping.class);
	//			PostMapping postMapping = declaredMethods.get(i).getDeclaredAnnotation(PostMapping.class);
	//			PreAuthorize preAuthorize = declaredMethods.get(i).getDeclaredAnnotation(PreAuthorize.class);
	//			System.out.println("Get相关的："+ JSON.toJSONString(getMapping));
	//			System.out.println("Post相关的："+JSON.toJSONString(postMapping));
	//			System.out.println("PreAuthorize相关的："+JSON.toJSONString(preAuthorize));
	//		}
	//
	//	}
	//	System.out.println();
	//}
	/**
	 * 更新销售订单结算
	 *
	 * @param saleOrderSettlement 实体对象
	 */
	@Override
	public SaleOrderSettlement updateSaleOrderSettlement(SaleOrderSettlement saleOrderSettlement){
		//TODO:请在此校验参数的合法性
		this.validateUpdateSaleOrderSettlement(saleOrderSettlement);
		Long rows = this.saleOrderSettlementDao.updateSaleOrderSettlement(saleOrderSettlement);
		if(rows != 1)
		{
			String error = "修改保存销售订单结算出错，数据库应该返回1,但返回了 "+rows+",数据可能被删除";
			throw new BusinessException(error);
		}
		return saleOrderSettlement;
	}

	/**
	 * 根据ID删除销售订单结算
	 *
	 * @param saleOrderSettlementId ID
	 */
	@Override
	public void deleteSaleOrderSettlement(Long saleOrderSettlementId){
		//TODO:请在此校验参数的合法性
		this.validateDeleteSaleOrderSettlement(saleOrderSettlementId);

		Map<Class<? extends BaseEntity>,EntityUsage> entityUsageMap = this.checkForeignEntity(SaleOrderSettlement.class, saleOrderSettlementId);
		if(entityUsageMap != null && entityUsageMap.size() >0){
			StringBuilder errors = new StringBuilder();
			errors.append("计划删除的数据正在被以下数引用\n");
			for(EntityUsage entityUsage : entityUsageMap.values()){
				errors.append("\t").append(entityUsage.getEntityLabel()).append("\n");
				for(Map.Entry<Long,String> entry : entityUsage.getUsageIdNames().entrySet() ){
					errors.append("\t\t").append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
				}
			}
			errors.append("，不能删除，请检查处理后再删除");
			throw  new BusinessException(errors.toString());
		}

		Long rows = this.saleOrderSettlementDao.deleteSaleOrderSettlement(saleOrderSettlementId);
		if(rows != 1){
			String error = "删除销售订单结算出错，数据可能已经被删除";
			throw new BusinessException(error);
		}
	}

	@Override
	public List<MenuSaleRecord> getMenuSaleRecordsByOrderId(Long orderId) {
		return this.menuSaleRecordService.findMenuSaleRecordByOrderId(orderId);
	}
	//TODO:---------------验证-------------------

	private void validateFindSaleOrderSettlements(PageDTO pageDTO) {
	//TODO:请使用下面方法添加数据过滤条件
	//		pageDTO.addFilter("creatorId",this.getLoginUserId());
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	private void validateFindSaleOrderSettlementsWithIdNameByName(String saleOrderSettlementName) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}


	private void validateFindAllSaleOrderSettlementsWithIdName() {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	private void validateFindSaleOrderSettlementsWithIdNameById(Long saleOrderSettlementId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	private void validateFindSaleOrderSettlement(Long saleOrderSettlementId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	private void validateFindSaleOrderSettlementWithForeignName(Long saleOrderSettlementId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	private void validateSaveSaleOrderSettlement(SaleOrderSettlement saleOrderSettlement) {
	//不为空判断
	if (saleOrderSettlement.getEid() != null || saleOrderSettlement.getCreatorId() != null || saleOrderSettlement.getCreateDatetime() != null) {
	throw new BusinessException("非法请求");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	private void validateUpdateSaleOrderSettlement(SaleOrderSettlement saleOrderSettlement) {
	//不为空判断
	if (saleOrderSettlement.getEid() == null) {
	throw new BusinessException("唯一标识不能为空");
	}
	//是否存在判断
	if (this.saleOrderSettlementDao.findSaleOrderSettlementTotalCount(PageDTO.create(SaleOrderSettlement.FIELD_ID, saleOrderSettlement.getEid())) == 0) {
	throw new BusinessException("修改的销售订单结算 " + saleOrderSettlement.getName() + " 不存在，修改失败，请重试或联系管理员");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	private void validateDeleteSaleOrderSettlement(Long saleOrderSettlementId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrderSettlement()写法
	}

	@Override
	public boolean canDownloadAttachment(String formName, Long id) {
	return true;
	}
}
